﻿/// Author: Eric Delahaye
/// Date: 2/2010
/// ----------------------------------------------------------------------------------------
/// Días desde  Porcentaje      Nombre en           Nombre en           Traducción 
/// Luna Nueva  iluminado       Español             Inglés              aproximada 
/// ----------------------------------------------------------------------------------------
/// 0               0%          Luna Nueva          New Moon            Luna Nueva 
/// 4               25%                             Waxing Crescent     Creciente Iluminante 
/// 7               50%         Cuarto Creciente    First Quarter       Primer Cuarto 
/// 10              75%                             Waxing Gibbous      Gibosa Iluminante 
/// 14              100%        Luna Lena           Full Moon           Luna Llena 
/// 18              75%                             Waning Gibbous      Gibosa Menguante 
/// 22              50%         Cuarto Menguante    Last Quarter        Último cuarto 
/// 26              25%                             Wanning Crescent    Creciente Menguante 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LunarPhase.Model
{
    public class Moon
    {
        private double percentageIlluminated = 0;
        public static double MaxMoonAge = 29.530588853;

        /// <summary>
        /// The age of the moon when it is 100% illuminated
        /// </summary>
        public static double TopLightAge
        {
            get
            {
                return Moon.MaxMoonAge / 2;
            }
        }

        public virtual LunarPhase Phase { get; private set; }

        public virtual double MoonAge { get; private set; }

        public Zodiac Sign { get; private set; }

        public virtual double PercentageIlluminated
        {
            get
            {
                return percentageIlluminated;
            }
            private set
            {
                percentageIlluminated = value;
            }
        }

        public virtual DateTime Date { get; private set; }

        /// <summary>
        /// Default contructor create the current moon
        /// </summary>
        public Moon()
        {
            this.Date = DateTime.Now;
            // this.Date = new DateTime(2010, 02, 15); // New Moon
            this.Initialize();
        }

        /// <summary>
        /// Create the moon for the date specified
        /// </summary>
        public Moon(DateTime date)
        {
            this.Date = date;
            this.Initialize();
        }

        /// <summary>
        /// Init all moon's values like a internal factory
        /// </summary>
        private void Initialize()
        {
            PhaseCalculator lunarFhaseCalculator = new PhaseCalculator();
            var moonBasicData = lunarFhaseCalculator.Calculate(this.Date);
            moonBasicData.Sign = this.ImproveSign();
            this.MoonAge = moonBasicData.AgeDays;
            this.Phase = moonBasicData.Phase;
            this.Sign = moonBasicData.Sign;
            this.SetPercentageIlluminated();
        }


        /// <summary>
        /// Takes into account the time and the time zone
        /// </summary>
        /// <returns>Zodiac</returns>
        private Zodiac ImproveSign()
        {
            MoonSignCalculator signCalculator = new MoonSignCalculator();
            return signCalculator.Calculate(this.Date, TimeZoneInfo.Local.BaseUtcOffset.Hours);
        }

        /// <summary>
        /// Set the percentage of moon illumintation
        /// </summary>
        private void SetPercentageIlluminated()
        {
            this.percentageIlluminated = this.AbsoluteToRelativeLight(this.MoonAge);
        }

        private double AbsoluteToRelativeLight(double absoluteLight)
        {
            switch (this.Phase)
            {
                case LunarPhase.NEW:
                    return 0;
                case LunarPhase.WaningCrescent:
                    return 25;
                case LunarPhase.FirstQuarter:
                    return 50;
                case LunarPhase.WaxingGibbous:
                    return 75;
                case LunarPhase.FULL:
                    return 100;
                case LunarPhase.WaningGibbous:
                    return 75;
                case LunarPhase.LastQuarter:
                    return 50;
                case LunarPhase.WaxingCrescent:
                    return 25;
                default:
                    return 0;
            }
        }

        public override string ToString()
        {
            return this.Phase.ToString();
        }

        // override object.Equals
        public override bool Equals(object obj)
        {
            //       
            // See the full list of guidelines at
            //   http://go.microsoft.com/fwlink/?LinkID=85237  
            // and also the guidance for operator== at
            //   http://go.microsoft.com/fwlink/?LinkId=85238
            //

            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }

            var toCompare = obj as Moon;
            return toCompare.Date.ToShortDateString() == this.Date.ToShortDateString();
        }

        // override object.GetHashCode
        public override int GetHashCode()
        {
            return base.GetHashCode() + this.Date.ToShortDateString().GetHashCode();
        }
    }
}